﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using Azure.Configuration;
using Azure.Logger;

namespace Azure.Core
{
    public class AzCoreEngine
    {
        private Dictionary<string, AzRobot> _robotDict = null;
        private Object _lock = null;
        private AutoResetEvent _completeEvent = null;
        private int _uncompletedRobotCount = 0;

        private static AzCoreEngine _instance = new AzCoreEngine();

        public static AzCoreEngine Instance { get { return _instance; } }

        private AzCoreEngine()
        {
            _robotDict = new Dictionary<string, AzRobot>();
            _lock = new Object();
            _completeEvent = new AutoResetEvent(false);
        }

        public void WaitForComplete()
        {
            _completeEvent.WaitOne();
        }

        public void Init()
        {
            foreach (AzRobotConfigItem robConfig in AzConfigManager.AllRobotConfig.Values)
            {
                AzRobot robot = null;
                try
                {
                    robot = new AzRobot(robConfig);

                    robot.NewTaskFoundEvent += OnNewTaskFoundEvent;
                    robot.RobotCompleteEvent += OnRobotCompleteEvent;
                }
                catch (Exception ex)
                {
                    AzLogger.Error(ex);
                    continue;
                }

                _robotDict.Add(robot.Name, robot);
            }

            _uncompletedRobotCount = _robotDict.Count;

            //没有机器人需要运行
            if (_uncompletedRobotCount == 0)
            {
                AzLogger.Warn("核心引擎没有成功创建任何一个机器人，执行即将结束");
                _completeEvent.Set();
            }
        }

        public void Start()
        {
            foreach (AzRobot robot in _robotDict.Values)
            {
                AzLogger.Important("机器人" + robot.Name + "启动");
                robot.Begin();
            }
        }

        private class NewTaskThreadParam
        {
            public AzRobot Robot { get; set; }
            public AzNewTask Task { get; set; }
        }

        private void OnNewTaskFoundEvent(AzRobot sender, List<AzNewTask> taskContext)
        {
            foreach (AzNewTask task in taskContext)
            {
                NewTaskThreadParam param = new NewTaskThreadParam();
                param.Robot = sender;
                param.Task = task;
                ThreadPool.QueueUserWorkItem(this.ThreadExecutor, param);
            }
        }

        private void ThreadExecutor(Object param)
        {
            AzRobot robot = ((NewTaskThreadParam)param).Robot;
            AzNewTask task = ((NewTaskThreadParam)param).Task;
            robot.Execute(task);
        }

        private void OnRobotCompleteEvent(AzRobot sender)
        {
            lock (this._lock)
            {
                if (--_uncompletedRobotCount == 0)
                {
                    AzLogger.Important("所有机器人都完成了工作");
                    _completeEvent.Set();
                }
            }
        }
    }
}
